using System.Collections;
using Microsoft.VisualBasic.FileIO;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;//namespace chua ham process
using System.Runtime.InteropServices;

namespace Windows_Explorer.Class
{
    [StructLayout(LayoutKind.Sequential)]
    public struct SHFILEINFO
    {
        public IntPtr hIcon;
        public IntPtr iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    };

    class Win32
    {
        public const uint SHGFI_ICON = 0x100;
        public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
        public const uint SHGFI_SMALLICON = 0x1; // 'Small icon

        [DllImport("shell32.dll")]
        public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
    }

    class clsTreeView
    {
        private static string path = "";
        public string Path
        {
            get
            {
                return path;
            }
            set 
            {
                path = value;
            }
        }

        /// <summary>
        /// Create TreeView, can chose the root folder of TreeView.
        /// </summary>
        /// <param name="tv"></param>
        /// <returns></returns>
        public static bool CreateTreeView(TreeView tv)
        {
            bool flag = false;
            try
            {
                //Desktop : root
                TreeNode desktop = new TreeNode();
                desktop.Text = "Desktop";
                desktop.Tag = "Desktop";
                desktop.ImageKey = "Desktop";
                desktop.SelectedImageKey = "Desktop";
                DirectoryInfo DesktopFolder = new DirectoryInfo(SpecialDirectories.Desktop);
                foreach (DirectoryInfo di in DesktopFolder.GetDirectories())
                {
                    TreeNode folder = new TreeNode(di.Name);
                    folder.Nodes.Add("");
                    folder.SelectedImageKey = "Folder";
                    folder.ImageKey = "Folder";
                    desktop.Nodes.Add(folder);
                }
                //My Documents : node[0]
                TreeNode MyDocuments = new TreeNode();
                MyDocuments.Text = "My Documents";
                MyDocuments.Tag = "Documents";
                MyDocuments.ImageKey = "Document";
                MyDocuments.SelectedImageKey = "Document";
                MyDocuments.Nodes.Add("");
                //My Computer : node[1]
                TreeNode MyComputer = new TreeNode();
                MyComputer.Text = "My Computer";
                MyComputer.Tag = "Computer";
                MyComputer.ImageKey = "Computer";
                MyComputer.SelectedImageKey = "Computer";
                foreach (DriveInfo drvi in DriveInfo.GetDrives())
                {
                    TreeNode tnDrv = new TreeNode();
                    string imgKey = DriveTypeImageKey(drvi);
                    tnDrv.SelectedImageKey = imgKey;
                    tnDrv.ImageKey = imgKey;
                    tnDrv.Text = drvi.Name;
                    tnDrv.Nodes.Add("");
                    MyComputer.Nodes.Add(tnDrv);
                }
                desktop.Nodes.Insert(0, MyDocuments);
                desktop.Nodes.Insert(1, MyComputer);
                tv.Nodes.Add(desktop);
                flag = true;
            }
            catch(Exception ex)
            {
                flag = false;
                ShowError(ex);
            }
            return flag;
        }

        /// <summary>
        /// Make image with type of Drive. Loop all kind of Drive.
        /// </summary>
        /// <param name="drvi"></param>
        /// <returns></returns>
        private static string DriveTypeImageKey(DriveInfo drvi)
        {
            string key = "";
            switch (drvi.DriveType)
            {
                case DriveType.Fixed:
                    {
                        key = "HDD";
                        break;
                    }
                case DriveType.CDRom:
                    {
                        key = "CD";
                        break;
                    }
                case DriveType.Network:
                    {
                        key = "NET";
                        break;
                    }
                case DriveType.Removable:
                    {
                        key = "RD";
                        break;
                    }
                case DriveType.Unknown:
                    {
                        key = "Folder";
                        break;
                    }
                default:
                    {
                        key = "HDD";
                        break;
                    }
            }
            return key;
        }

        /// <summary>
        /// If system have errors, dialog will be shown to the user.
        /// </summary>
        /// <param name="ex"></param>
        public static void ShowError(Exception ex)
        {
            MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        /// <summary>
        /// Display when path is not valid. Dialog will be display if you select wrong path of folder.
        /// </summary>
        public void ShowErrorPath()
        {
            MessageBox.Show("Invalid path!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parentNode"></param>
        /// <returns></returns>
        public static TreeNode Expand(TreeNode parentNode)
        {
            try
            {
                DirectoryInfo rootDir = GetRootDir(parentNode);
                path = rootDir.FullName;
                parentNode.Nodes[0].Remove();
                foreach (DirectoryInfo di in rootDir.GetDirectories())
                {
                    TreeNode tn = new TreeNode();
                    tn.Text = di.Name;
                    tn.Nodes.Add("");
                    parentNode.Nodes.Add(tn);
                }
            }
            catch(Exception ex) 
            {
                ShowError(ex);
            }
            return parentNode;
        }
        public static string GetPath(TreeNode parentNode)
        {
            if (parentNode.Text == "Desktop") return null;
            char[] arr ={ '\\' };
            string path = "";
            string[] nameList = parentNode.FullPath.Split(arr);
            string nodeName = nameList.GetValue(1).ToString();
            switch (nodeName)
            {
                case "My Documents":
                    path = SpecialDirectories.MyDocuments + "\\";
                    break;
                case "My Computer":
                    path = "MyComputer";
                    break;
                default:
                    path = "";
                    break;
            }
            if (path == "")
                path = SpecialDirectories.Desktop + "\\";
            string pathNew = path + nodeName + "\\";
            DirectoryInfo di = new DirectoryInfo(pathNew);
            if (di.Exists)
            {
                path = pathNew;
            }
            return path;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parentNode"></param>
        /// <returns></returns>
        private static DirectoryInfo GetRootDir(TreeNode parentNode)
        {
            char[] arr ={ '\\' };
            string path = "";
            string[] nameList = parentNode.FullPath.Split(arr);
            string nodeName = nameList.GetValue(1).ToString();
            if (nameList.GetValue(0).ToString() == "Desktop" && nodeName != "My Documents" && nodeName != "My Computer")
            {
                path = SpecialDirectories.Desktop + "\\";
                if (nameList.Length >= 2) path += nameList[1] + "\\";
            }
            else
            {
                switch (nodeName)
                {
                    case "My Documents":
                        path = SpecialDirectories.MyDocuments + "\\";
                        break;
                    default:
                        path = "";
                        break;
                }
            }
            for (int i = 2; i < nameList.Length; i++)
                path += nameList[i] + "\\";
            return new DirectoryInfo(path);
        }
        public void OpenFolder(ListViewItem lvItem, ListView listView)
        {
            try
            {
                string path = lvItem.SubItems[4].Text;
                if (path == "MyComputer")
                {
                    GetAllDriver(listView);
                    return;
                }
                FileInfo fi = new FileInfo(path);
                if (fi.Exists)
                {
                    Process.Start(path);
                }
                else
                {
                    DirectoryInfo rootDir = new DirectoryInfo(path + "\\");
                    if (!rootDir.Exists)
                    {
                        ShowErrorPath();
                        return;
                    }
                    GetAllInDirectory(rootDir, listView);
                }
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }
        /* Sai
        public int i = 0;
        public void parent(TreeView tvw, TreeNode tn, string fullPath)
        {
            try
            {
                string[] pathArr = fullPath.Split('\\');
                if (tn.Text != "")
                {
                    foreach (TreeNode t in tn.Nodes)
                    {
                        if (t.Text != "")
                        {
                            for (i = 0; i < pathArr.Length; i++)
                            {
                                if (!t.FullPath.Contains(pathArr[i])) break;
                            }
                            if (i == pathArr.Length)
                            {
                                tvw.SelectedNode = t;
                                tvw.SelectedNode.Expand();
                            }
                            else
                                parent(tvw, t, fullPath);
                        }
                    }
                }
            }
            catch { }
        }
        */
        public void OpenFolder(string path, ListView listView)
        {
            try
            {
                if (!path.EndsWith("\\"))
                    path += "\\";
                char[] arr ={ '\\' };
                string[] nameList = path.Split(arr);
                string node1 = nameList.GetValue(1).ToString();
                if (nameList.GetValue(0).ToString() == "Desktop" && node1 != "My Documents" && node1 != "My Computer")
                {
                    path = SpecialDirectories.Desktop + "\\";
                    for (int i = 2; i < nameList.Length; i++)
                        path += nameList[i] + "\\";
                }
                DirectoryInfo rootDir = new DirectoryInfo(path);
                if (!rootDir.Exists)
                {
                    ShowErrorPath();
                    return;
                }
                GetAllInDirectory(rootDir, listView);
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }
        public  void OpenFolder(TreeNode treeNode, ListView listView)
        {
            try
            {
                DirectoryInfo rootDir = null;
                if (treeNode.Text == "Desktop")
                {
                    GetDesktop(treeNode, listView);
                    return;
                }

                if (treeNode.Parent.Text == "Desktop")
                {
                    string nodeName = treeNode.Text;
                    switch (nodeName)
                    {
                        case "My Computer":
                            GetAllDriver(listView);
                            break;
                        case "My Documents":
                            rootDir = GetRootDir(treeNode);
                            GetAllInDirectory(rootDir, listView);
                            break;
                        default://sub directory
                            rootDir = new DirectoryInfo(SpecialDirectories.Desktop + "\\" + treeNode.Text + "\\");
                            GetAllInDirectory(rootDir, listView);
                            break;
                    }
                }
                else
                {
                    rootDir = GetRootDir(treeNode);
                    GetAllInDirectory(rootDir, listView);
                }
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }
        
        public void ParentFolder(ListView listView, TreeView treeView)
        {
            try
            {
                //Desktop
                if (Path == "Desktop" || Path == "MyComputer")
                {
                    GetDesktop(treeView.Nodes[0], listView);
                    return;
                }
                //if (this.Path == "MyComputer")
                //{
                //    GetAllDriver(listView);
                //    return;
                //}
                DirectoryInfo rootDir = new DirectoryInfo(Path);
                if (!rootDir.Exists)
                {
                    ShowErrorPath();
                    return;
                }
                if (rootDir.FullName.Equals(rootDir.Root.FullName))
                {
                    GetAllDriver(listView);
                }
                else
                {
                    GetAllInDirectory(rootDir.Parent, listView);
                }
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }
        public void GetAllDriver(ListView listView)
        {
            try
            {
                ListViewItem item;
                listView.Items.Clear();
                foreach (DriveInfo drv in DriveInfo.GetDrives())
                {
                    if (drv.IsReady)
                    {
                        item = CreatLVItem(drv);
                        listView.Items.Add(item);
                    }
                }
                this.Path = "MyComputer";
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }

        /// <summary>
        /// Get all folders and files, then add to listView for displaying
        /// </summary>
        /// <param name="rootDir"></param>
        /// <param name="listView"></param>
        private void GetAllInDirectory(DirectoryInfo rootDir, ListView listView)
        {
            try
            {
                Dictionary<String, String> result = new Dictionary<string, string>();
                result = FileUtils.readDataFromFile(System.IO.Path.GetFullPath(@"C:\Users\lemon1707\Desktop\Website") + "\\" + "color.txt");
                ListViewItem item;
                listView.Items.Clear();
                foreach (DirectoryInfo dir in rootDir.GetDirectories())
                {
                    item = CreatLVItem(dir);
                    if (result.ContainsKey(item.Text))
                    {
                        item.BackColor = System.Drawing.Color.Blue;
                    }
                    listView.Items.Add(item);
                    

                }
                foreach (FileInfo file in rootDir.GetFiles())
                {
                    item = CreatLVItem(file);
                    listView.Items.Add(item);
                }
                this.Path = rootDir.FullName;
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }
        public void GetDesktop(TreeNode treeNode, ListView listView)
        {
            try
            {
                ListViewItem item;
                listView.Items.Clear();
                for (int i = 0; i < treeNode.Nodes.Count; i++)
                {
                    item = CreatLVItem(treeNode.Nodes[i]);
                    listView.Items.Add(item);
                }
                DirectoryInfo rootDir = new DirectoryInfo(SpecialDirectories.Desktop);
                foreach (FileInfo file in rootDir.GetFiles())
                {
                    item = CreatLVItem(file);
                    listView.Items.Add(item);
                }
                this.Path = "Desktop";
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }

        /// <summary>
        /// Create property of item, add to listView as Folder.
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static ListViewItem CreatLVItem(DirectoryInfo dir)
        {
            string[] s = { dir.Name, "File Folder", "", dir.LastWriteTime.ToString(), dir.FullName, dir.Parent.FullName };
            ListViewItem item = new ListViewItem(s);
            if (dir.Attributes.ToString().Contains("Hidden")) item.ImageKey = "Hidden";
            else
                item.ImageKey = "Folder";
            return item;
        }

        /// <summary>
        /// Create property of item, add to listView as File.
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static ListViewItem CreatLVItem(FileInfo file)
        {
            long size = file.Length / 1024;
            string[] s = { file.Name, file.Extension.ToUpper(), size + " KB", 
                file.LastWriteTime.ToString(), file.FullName, file.Directory.FullName };
            ListViewItem item = new ListViewItem(s);
            item.ImageKey=ImageKey(file);
            return item;
        }

        /// <summary>
        /// Return the image key with appropriate extension of File
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static string ImageKey(FileInfo file)
        {
            switch (file.Extension.ToUpper())
            {
                case ".MSI":
                    return "setup";
                    break;
                case ".TXT":
                case ".DIZ":
                case ".LOG":
                case".CPP":
                    return "txt";
                    break;
                case ".PDF":
                    return "pdf";
                    break;
                case ".HTM":
                case "HTML.":
                    return "htm";
                    break;
                case ".DOC":
                case".DOCX":
                    return "doc";
                    break;
                case ".EXE":
                    return "exe";
                    break;
                case ".JPG":
                case ".BMP":
                    return "bmp";
                    break;
                case ".SLN":
                    return "sln";
                    break;
                case ".MP3":
                case ".WAV":
                case ".WMV":
                case ".ASF":
                case ".MPEG":
                case ".AVI":
                    return "music";
                    break;
                case ".RAR":
                case ".ZIP":
                case ".ISO":
                    return "rar";
                    break;
                //case ".DLL":
                //case ".REG":
                case ".INI":
                case ".INF":
                    return "inf";
                    break;
                case ".SWF":
                case ".FLV":
                case ".FLA":
                    return "swf";
                    break;
                default:
                    return "File";
                    break;
            }
            if (file.Name.ToString().ToUpper() == "SETUP.EXE") return "setup";
        }
       
        public static void OpenTreeNode(TreeView tvw, string FullPath)
        {
            string[] FullPathArr = FullPath.Split('\\');
            string key = FullPathArr[FullPathArr.Length - 1];
        }
        public static ListViewItem CreatLVItem(DriveInfo drv)
        {
            string name = "";
            string driveType = "";
            string size = "";
            string free = "";

            if (drv.DriveType != DriveType.CDRom && drv.DriveType != DriveType.Removable)
            {
                double t = Math.Round((double)drv.TotalSize / (1024 * 1024 * 1024), 2);
                double f = Math.Round((double)drv.AvailableFreeSpace / (1024 * 1024 * 1024), 2);

                size = t + " GB";
                free = f + " GB";

                if (drv.VolumeLabel != null)
                    name = drv.VolumeLabel + " " + drv.Name;
            }
            else
            {
                name = drv.Name;
            }
            driveType = drv.DriveType.ToString();
            string[] s = { name, driveType, size, free, drv.Name, "" };
            ListViewItem item = new ListViewItem(s);
            item.ImageKey = DriveTypeImageKey(drv);
            return item;
        }
        private static ListViewItem CreatLVItem(TreeNode treeNode)
        {
            ListViewItem item = null;
            if (treeNode.Parent.Text == "Desktop")
            {
                string path = GetPath(treeNode);
                DirectoryInfo di = new DirectoryInfo(path);
                if (di.Exists && di.Name != "My Documents")
                {
                    string[] folder = { treeNode.Text, "File Folder", "", di.LastWriteTime.ToString(), path, "Desktop" };
                    item = new ListViewItem(folder);
                    if (treeNode.ImageKey.Trim() != string.Empty)
                        item.ImageKey = treeNode.ImageKey;
                    else
                        item.ImageKey = "Folder";
                }
                else
                {
                    string[] s = { treeNode.Text, "", "", "", path, "Desktop" };
                    item = new ListViewItem(s);
                    if (treeNode.ImageKey.Trim() != string.Empty)
                        item.ImageKey = treeNode.ImageKey;
                    else
                        item.ImageKey = "Default";
                }
            }
            return item;
        }
        
        #region History
        clsHistory history = new clsHistory();
        public void HistoryAdd()
        {
            history.Add(this.Path);
        }
        public string HistoryBack(ListView listView, TreeNode treeNode)
        {
            return OpenHistory(history.Back(), listView, treeNode);
        }
        public string HistoryForward(ListView listView, TreeNode treeNode)
        {
            return OpenHistory(history.Forward(), listView, treeNode);
        }
        public string OpenHistory(string path, ListView listView, TreeNode treeNode)
        {
            switch (path)
            {
                case null:
                    break;
                case "Desktop":
                    GetDesktop(treeNode, listView);
                    break;
                case "MyComputer":
                    GetAllDriver(listView);
                    break;
                default:
                    OpenFolder(path, listView);
                    break;
            }
            return path;
        }
        #endregion

    }
}
